import { Injectable, NotFoundException, ConflictException, Logger } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository, SelectQueryBuilder } from 'typeorm';
import { Menu } from './entities/menu.entity';
import { CreateMenuDto } from './dto/create-menu.dto';
import { UpdateMenuDto } from './dto/update-menu.dto';
import { QueryMenuDto } from './dto/query-menu.dto';
import { PaginationResponseDto } from '../common/dto/pagination.dto';
import * as bcrypt from 'bcryptjs';

@Injectable()
export class MenusService {
  private readonly logger = new Logger(MenusService.name);

  constructor(
    @InjectRepository(Menu)
    private menusRepository: Repository<Menu>,
  ) {}

  async create(createMenuDto: CreateMenuDto): Promise<Menu> {
    this.logger.log(`创建菜单请求: ${JSON.stringify(createMenuDto)}`);
    
    // 检查菜单名称是否已存在（同级下）
    const existingMenu = await this.menusRepository.findOne({
      where: {
        name: createMenuDto.name,
        parent_id: createMenuDto.parent_id || 0
      }
    });

    if (existingMenu) {
      this.logger.warn(`菜单创建失败: 同级下菜单名称已存在 - ${createMenuDto.name}`);
      throw new ConflictException('同级下菜单名称已存在');
    }

    // 计算菜单层级
    let level = 1;
    if (createMenuDto.parent_id && createMenuDto.parent_id > 0) {
      const parentMenu = await this.menusRepository.findOne({
        where: { id: createMenuDto.parent_id }
      });
      if (!parentMenu) {
        throw new NotFoundException('父菜单不存在');
      }
      level = parentMenu.level + 1;
    }

    // 设置默认值
    const menuData = {
      ...createMenuDto,
      level,
      sort: createMenuDto.sort || 0,
      parent_id: createMenuDto.parent_id || 0,
      type: createMenuDto.type || 'menu',
      is_visible: createMenuDto.is_visible !== undefined ? createMenuDto.is_visible : true,
      is_enabled: createMenuDto.is_enabled !== undefined ? createMenuDto.is_enabled : true,
      target: createMenuDto.target || '_self'
    };

    const menu = this.menusRepository.create(menuData);
    const savedMenu = await this.menusRepository.save(menu);
    
    this.logger.log(`菜单创建成功: ${savedMenu.name}, ID: ${savedMenu.id}, 层级: ${savedMenu.level}`);
    
    return savedMenu;
  }

  async findAll(): Promise<Menu[]> {
    this.logger.log('获取所有菜单列表');
    const menus = await this.menusRepository.find({
      order: { sort: 'ASC', id: 'ASC' }
    });
    this.logger.log(`找到 ${menus.length} 个菜单`);
    return menus;
  }

  async findWithPagination(queryDto: QueryMenuDto): Promise<PaginationResponseDto<Menu>> {
    this.logger.log(`分页查询菜单: ${JSON.stringify(queryDto)}`);

    const {
      page = 1,
      pageSize = 10,
      name,
      path,
      type,
      parent_id,
      level,
      is_visible,
      is_enabled,
      permission,
      sortBy = 'sort',
      sortOrder = 'ASC'
    } = queryDto;

    // 构建查询
    const queryBuilder = this.buildMenuQueryBuilder({
      name,
      path,
      type,
      parent_id,
      level,
      is_visible,
      is_enabled,
      permission
    });

    // 添加排序
    queryBuilder.orderBy(`Menu.${sortBy}`, sortOrder);

    // 获取总数
    const total = await queryBuilder.getCount();
    this.logger.log(`查询到总菜单数: ${total}`);

    // 分页查询
    const skip = (page - 1) * pageSize;
    const menus = await queryBuilder
      .skip(skip)
      .take(pageSize)
      .getMany();

    this.logger.log(`分页查询结果: 第${page}页，每页${pageSize}条，实际返回${menus.length}条`);

    // 计算分页信息
    const totalPages = Math.ceil(total / pageSize);
    const hasPrevious = page > 1;
    const hasNext = page < totalPages;

    return {
      data: menus,
      total,
      page,
      pageSize,
      totalPages,
      hasPrevious,
      hasNext
    };
  }

  private buildMenuQueryBuilder(filters: {
    name?: string;
    path?: string;
    type?: string;
    parent_id?: number;
    level?: number;
    is_visible?: boolean;
    is_enabled?: boolean;
    permission?: string;
  }): SelectQueryBuilder<Menu> {
    const queryBuilder = this.menusRepository.createQueryBuilder('Menu');

    // 菜单名称搜索
    if (filters.name) {
      queryBuilder.andWhere('Menu.name LIKE :name', { name: `%${filters.name}%` });
    }

    // 菜单路径搜索
    if (filters.path) {
      queryBuilder.andWhere('Menu.path LIKE :path', { path: `%${filters.path}%` });
    }

    // 菜单类型筛选
    if (filters.type) {
      queryBuilder.andWhere('Menu.type = :type', { type: filters.type });
    }

    // 父菜单ID筛选
    if (filters.parent_id !== undefined) {
      queryBuilder.andWhere('Menu.parent_id = :parent_id', { parent_id: filters.parent_id });
    }

    // 菜单层级筛选
    if (filters.level !== undefined) {
      queryBuilder.andWhere('Menu.level = :level', { level: filters.level });
    }

    // 可见性筛选
    if (filters.is_visible !== undefined) {
      queryBuilder.andWhere('Menu.is_visible = :is_visible', { is_visible: filters.is_visible });
    }

    // 启用状态筛选
    if (filters.is_enabled !== undefined) {
      queryBuilder.andWhere('Menu.is_enabled = :is_enabled', { is_enabled: filters.is_enabled });
    }

    // 权限标识搜索
    if (filters.permission) {
      queryBuilder.andWhere('Menu.permission LIKE :permission', { permission: `%${filters.permission}%` });
    }

    return queryBuilder;
  }

  async findOne(id: number): Promise<Menu> {
    this.logger.log(`查找菜单ID: ${id}`);
    
    const menu = await this.menusRepository.findOne({
      where: { id }
    });

    if (!menu) {
      this.logger.warn(`菜单不存在: ID ${id}`);
      throw new NotFoundException(`菜单ID ${id} 不存在`);
    }

    this.logger.log(`找到菜单: ${menu.name}, ID: ${menu.id}`);
    return menu;
  }

  async findTree(): Promise<Menu[]> {
    this.logger.log('获取菜单树形结构');
    
    const allMenus = await this.menusRepository.find({
      order: { sort: 'ASC', id: 'ASC' }
    });

    const menuTree = this.buildMenuTree(allMenus);
    this.logger.log(`构建菜单树完成，顶级菜单数量: ${menuTree.length}`);
    
    return menuTree;
  }

  private buildMenuTree(menus: Menu[], parentId: number = 0): Menu[] {
    const tree: Menu[] = [];
    
    for (const menu of menus) {
      if (menu.parent_id === parentId) {
        const children = this.buildMenuTree(menus, menu.id);
        if (children.length > 0) {
          menu.children = children;
          menu.hasChildren = true;
        } else {
          menu.hasChildren = false;
        }
        tree.push(menu);
      }
    }
    
    return tree;
  }

  async update(id: number, updateMenuDto: UpdateMenuDto): Promise<Menu> {
    this.logger.log(`更新菜单ID: ${id}, 更新数据: ${JSON.stringify(updateMenuDto)}`);
    
    const menu = await this.findOne(id);

    // 检查菜单名称是否重复（同级下）
    if (updateMenuDto.name && updateMenuDto.name !== menu.name) {
      const existingMenu = await this.menusRepository.findOne({
        where: {
          name: updateMenuDto.name,
          parent_id: updateMenuDto.parent_id !== undefined ? updateMenuDto.parent_id : menu.parent_id
        }
      });

      if (existingMenu && existingMenu.id !== id) {
        this.logger.warn(`菜单更新失败: 同级下菜单名称已存在 - ${updateMenuDto.name}`);
        throw new ConflictException('同级下菜单名称已存在');
      }
    }

    // 如果更新父菜单，需要重新计算层级
    if (updateMenuDto.parent_id !== undefined && updateMenuDto.parent_id !== menu.parent_id) {
      let newLevel = 1;
      if (updateMenuDto.parent_id > 0) {
        const parentMenu = await this.menusRepository.findOne({
          where: { id: updateMenuDto.parent_id }
        });
        if (!parentMenu) {
          throw new NotFoundException('父菜单不存在');
        }
        newLevel = parentMenu.level + 1;
      }
      updateMenuDto.level = newLevel;
      
      // 递归更新所有子菜单的层级
      await this.updateChildrenLevel(id, newLevel + 1);
    }

    Object.assign(menu, updateMenuDto);
    const updatedMenu = await this.menusRepository.save(menu);
    
    this.logger.log(`菜单更新成功: ${updatedMenu.name}, ID: ${updatedMenu.id}`);
    
    return updatedMenu;
  }

  private async updateChildrenLevel(parentId: number, newLevel: number): Promise<void> {
    const children = await this.menusRepository.find({
      where: { parent_id: parentId }
    });

    for (const child of children) {
      child.level = newLevel;
      await this.menusRepository.save(child);
      
      // 递归更新子菜单
      await this.updateChildrenLevel(child.id, newLevel + 1);
    }
  }

  async remove(id: number): Promise<void> {
    this.logger.log(`删除菜单ID: ${id}`);
    
    const menu = await this.findOne(id);

    // 检查是否有子菜单
    const childrenCount = await this.menusRepository.count({
      where: { parent_id: id }
    });

    if (childrenCount > 0) {
      this.logger.warn(`菜单删除失败: 存在子菜单，无法删除 - ${menu.name}`);
      throw new ConflictException('存在子菜单，无法删除');
    }

    await this.menusRepository.remove(menu);
    
    this.logger.log(`菜单删除成功: ${menu.name}, ID: ${id}`);
  }

  async getMenuOptions(): Promise<{ id: number; name: string; level: number }[]> {
    this.logger.log('获取菜单选项列表');
    
    const menus = await this.menusRepository.find({
      select: ['id', 'name', 'level'],
      where: { type: 'menu', is_enabled: true },
      order: { sort: 'ASC', id: 'ASC' }
    });

    return menus.map(menu => ({
      id: menu.id,
      name: '　'.repeat(menu.level - 1) + menu.name, // 使用全角空格缩进
      level: menu.level
    }));
  }
}
